/**
 * 1.反射api与对象api
 * （1）不限于做捕获程序
 * （2）大多数反射api在opject中有对应方法
 */


/**
 * 2.状态标记
 * 有很多反射方法可以返回布尔值，用作判断状态
 */

//Object.defineProperty({},'foo','bar')


//初始代码
const o = {};
try {
    Object.defineProperty(o,'foo','bar')
    console.log('success成功');
} catch (error) {
    console.log('failure失败');
}

//重构代码
if (Reflect.defineProperty(o,'foo',{value:'bar'})) {
    console.log('success成功');
}else{
    console.log('failure失败');
}

/**
 * 小结:不用处理异常，代码更加健壮。
 */


/**
 * 2.有状态标记的方法
 * 1.Reflect.preventExtensions(target)
 * 参数 target 是阻止扩展的目标对象。该方法返回一个布尔值，表明目标对象是否成功被设置为不可扩展
 * 
 * 2.Reflect.setPrototypeOf 是 JavaScript 中的一个静态方法，用于设置指定对象的原型（即内部的 [[Prototype]] 属性）为另一个对象或 null。
 * 与 Object.setPrototypeOf() 方法相似，但 Reflect.setPrototypeOf 返回一个布尔值，表示操作是否成功
 * 
 * 3.Reflect.set(target, propertyKey, value[, receiver])这个方法与 Object.assign 或直接赋值操作（=）不同，它允许你设置对象属性的值，并且可以返回一个布尔值来表示操作是否成功。
 * 参数：
 * target：目标对象，其属性将被设置。
 * propertyKey：要设置的属性的名称或符号。
 * value：要设置的属性的新值。
 * receiver（可选）：如果提供了 receiver，则返回值将从这个对象继承属性，而不是 target。
 * 
 * 4.Reflect.deleteProperty(target, propertyKey) 用于删除对象的属性。这个方法尝试删除或不可配置的属性，并且会返回一个布尔值来表示操作是否成功。
 * 参数：
 * target：要在其上删除属性的对象。
 * propertyKey：要删除的属性的名称或符号。
 * 
 * 
 */
// 默认情况下，对象是可扩展的。
const empty = {};
console.log(Reflect.isExtensible(empty)); // true 可扩展的
// 可以将其变为不可扩展。
if (Reflect.preventExtensions(empty)) {
    console.log('对象成功被设置为不可扩展');
}

console.log(Reflect.isExtensible(empty)); // false 不可扩展


/**
 * 3.反射函数代替操作符
 * Reflect.set 代替 =赋值
 * Reflect.get 代替 .属性
 * Reflect.has 代替 in 或with()
 * Reflect.deleteProperty 代替   delete
 * Reflect.construct  代替 new
 */

/**
 * 4.安全地应用函数
 * Reflect.apply(target: 目标函数, thisArgument: 调用对象, argumentsList: 参数数组)
 * 
 */
{
    const per = {
        name:'jack'
    }
    const sayHello = function(){
        console.log(this.name+'hello!!');
    }
    Reflect.apply(sayHello,per,[])
}

